package com.kafka.xiang.agentcontrol;

import com.kafka.xiang.controller.ProducerController;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.kafka.xiang.common.Keyboard;
import com.kafka.xiang.common.Mouse;
import java.nio.charset.StandardCharsets;
import com.alibaba.fastjson.JSONObject;
import org.springframework.kafka.support.serializer.JsonSerializer;


public class ControlAgent {
    private KafkaTemplate<String,Object> kafkaTemplate;

    private final static Logger LOG = LoggerFactory.getLogger(ProducerController.class);
    private final static Properties prop = new Properties();

    // prop.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "gzip");
    private String[] producerTopic;
    private int height=0;
    private int width=0;

    public ControlAgent(String[] consumerTopic,String bootstrapServers ){
        this.producerTopic=consumerTopic;
        this.prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        this.prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        this.prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        this.prop.put(ProducerConfig.ACKS_CONFIG, "-1");
        this.prop.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG, 104857600);
        this.prop.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        this.prop.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); // 替换为实际的值的反序列化器类,值是字节流，所以是ByteArraySerializer

    }
    public byte[][] screenCapture() {
        try {
            // 创建 Robot 对象
            Robot robot = new Robot();
            // 获取默认屏幕设备
            GraphicsDevice defaultScreen = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

            // 获取默认屏幕设备的分辨率
            DisplayMode displayMode = defaultScreen.getDisplayMode();

            this.height=displayMode.getHeight();
            this.width=displayMode.getWidth();

            // 获取屏幕尺寸
            //Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            //this.height=screenSize.height;
            //this.width=screenSize.width;
            System.out.println("height:"+height+"width:"+width);
            // 创建一个矩形，用于表示屏幕的范围
            Rectangle screenRect = new Rectangle(width,height);

            // 截屏操作
            BufferedImage screenImage = robot.createScreenCapture(screenRect);
            File output=new File("./screen.png");
            ImageIO.write(screenImage,"png",output);
            System.out.println("截屏成功！");
            //保存成String
            StringBuffer s = new StringBuffer();
            //byte[] img = getBytes(screenImage);
            // 将 BufferedImage 转换为二维字节数组
            byte[][] img = convertTo2DByteArray(screenImage);
            return img;
        } catch (Exception e) {
            System.err.println("截屏失败：" + e.getMessage());
            return null;
        }
    }

    // 将BufferImage 转换为字节数组
    private  byte[] getBytes(BufferedImage image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "PNG", baos);
        } catch (Exception e) {
            LOG.info(String.valueOf(e));
        }
        return baos.toByteArray();
    }
    //二维字节数组
    private static byte[][] convertTo2DByteArray(BufferedImage image) throws IOException {
        int width = image.getWidth();
        int height = image.getHeight();
        byte[][] imageBytes = new byte[height][width * 3]; // Assuming 3 channels (RGB)

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int rgb = image.getRGB(x, y);
                imageBytes[y][x * 3] = (byte) ((rgb >> 16) & 0xFF); // Red
                imageBytes[y][x * 3 + 1] = (byte) ((rgb >> 8) & 0xFF); // Green
                imageBytes[y][x * 3 + 2] = (byte) (rgb & 0xFF); // Blue
            }
        }
        /*
        ByteArrayOutputStream baos =new ByteArrayOutputStream();
        for (byte[] row :imageBytes){
            baos.write(row);
        }
        byte[] screenhotBytes=baos.toByteArray();

         */
        return imageBytes;
    }

    //需要将二维数组展平为一维数组
    private byte[] flatten2DArray(byte[][] array2D) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (byte[] row : array2D) {
            try {
                baos.write(row);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return baos.toByteArray();
    }
    //二维字节数组直接转化为二进制字符串
    private static String convertToBinaryString(byte[][] originalByteArray) {
        StringBuilder binaryStringBuilder = new StringBuilder();

        for (byte[] row : originalByteArray) {
            for (byte value : row) {
                // 将每个字节转换为8位二进制字符串
                String byteString = String.format("%8s", Integer.toBinaryString(value & 0xFF)).replace(' ', '0');
                binaryStringBuilder.append(byteString);
            }
        }

        return binaryStringBuilder.toString();
    }

    //二进制字符串转化为字节数组
    private static byte[] convertBinaryStringToBytes(String binaryString) {
        int length = binaryString.length();
        byte[] result = new byte[length / 8];

        for (int i = 0; i < length; i += 8) {
            String byteString = binaryString.substring(i, i + 8);
            result[i / 8] = (byte) Integer.parseInt(byteString, 2);
        }

        return result;
    }



    private static Object parseData(String dataStr) {
        // Add logic to parse data based on its type
        if (dataStr.startsWith("'") && dataStr.endsWith("'")) {
            return dataStr.substring(1, dataStr.length() - 1); // Remove single quotes
        } else {
            try {
                return Integer.parseInt(dataStr); // Assume it's an integer
            } catch (NumberFormatException e) {
                return dataStr; // If parsing as integer fails, treat it as a string
            }
        }
    }

    public void actionExec(String input) throws AWTException {
        String actionType = null;
        Object[] actionData = null;
        Keyboard keyboard = new Keyboard();
        Mouse mouse =new Mouse();
        input=input.replace("\"","\'");
        // Using regular expression to extract action type and data
        Pattern pattern = Pattern.compile("(\\w+)\\(([^)]*)\\)");
        Matcher matcher = pattern.matcher(input);

        if (matcher.matches()) {
            actionType = matcher.group(1);
            if ("click".equals(actionType)) {
                mouse.click();
            } else if ("double_click".equals(actionType)) {
                mouse.doubleClick();
            } else if ("enter_text".equals(actionType)) {
                String dataStr = matcher.group(2);
                if (dataStr != null) {
                    keyboard.enterText(dataStr);
                } else {
                    System.out.println("Invalid enter_text action data");
                }
            } else {
                String[] dataStr = matcher.group(2).split(",");
                actionData = new Object[dataStr.length];

                for (int i = 0; i < dataStr.length; i++) {
                    actionData[i] = parseData(dataStr[i].trim());
                }
                if ("enter_fn".equals(actionType)) {
                    if (actionData != null && actionData.length == 2) {
                        keyboard.enterFn((String) actionData[0], (String) actionData[1]);
                    } else if (actionData != null && actionData.length == 3) {
                        keyboard.enterFn((String) actionData[0], (String) actionData[1], (String) actionData[2]);
                    } else {
                        System.out.println("Invalid enter_fn action data");
                    }
                } else if("enter".equals(actionType)){
                    if (actionData != null && actionData.length == 1){
                        keyboard.enter((String) actionData[0]);
                    } else {
                        System.out.println("Invalid enter action data");
                    }
                }
                else if("move".equals(actionType)){
                    if (actionData != null && actionData.length == 4) {
                        //第三第四个参数是高和宽，忽略
                        mouse.move((int) actionData[0], (int)actionData[1]);
                    } else {
                        System.out.println("Invalid enter_fn action data");
                    }
                }else {
                    System.out.println("Unknown action type: " + actionType);
                }
            }
        }
    }

    public void handler(String key, String JSvalue) {
        if ("update_gui_info".equals(key)) {
            //JSONObject jsonObject = JSONObject.parseObject(JSvalue);
            //String uuid = jsonObject.getString("uuid");

            KafkaProducer<String, String> producer = new KafkaProducer<String, String>(prop);
            byte[][] imageBytes = screenCapture();
            // 将二维字节数组转换为二进制字符串
            //String binaryString = convertToBinaryString(imageBytes);
            //byte[] binaryBytes = convertBinaryStringToBytes(binaryString);

            //System.out.println("二进制字符串长度:"+binaryString.length());
            // 将二维字节数组展平为一维字节数组
            byte[] flattenedBytes = flatten2DArray(imageBytes);
            // 对一维字节数组进行 Base64 编码
            String base64EncodedImage = Base64.getEncoder().encodeToString(flattenedBytes);
            String shape=String.format("(%d,%d)",height,width);
            // 创建一个包含 uuid 和 screen 的 jObject
            JSONObject jObject = new JSONObject();
            //jObject.put("uuid", uuid);
            jObject.put("uuid", "");
            jObject.put("shape",shape);
            jObject.put("img_byte", base64EncodedImage);
            // 将 JSONObject 转换为 JSON 字符串
            String jObjectStr = jObject.toJSONString();
            //String str = new String(s, StandardCharsets.UTF_8);//StandardCharsets.UTF_8 是指定的字符集。确保使用与编码时相同的字符集，以避免数据损失或错误。
            //byte[] bytes = data.getBytes(StandardCharsets.UTF_8);字符串转为byte[]
            //String str = Base64.getEncoder().encodeToString(s);
            //System.out.println(str.length());
            ProducerRecord<String, String> producerRecord1 = new ProducerRecord<>(this.producerTopic[0],"update_gui_info", jObjectStr);
            producer.send(producerRecord1);
            System.out.println("当前发送的topic是："+this.producerTopic[0]);
            //producer.send(new ProducerRecord<>(this.consumer_topic[0], "screen_control_data".getBytes(),this.screenCapture()));
        } else if ("processor_script".equals(key)) {
            JSONObject jsonObject = JSONObject.parseObject(JSvalue);

            String uuid = jsonObject.getString("uuid");
            String instruction = jsonObject.getString("instruction");
            try {
                LOG.info(instruction);//其中value是字符串:move(641, 670)、enter_fn('LCTRL', 'A')等等
                actionExec(instruction);
            }catch (AWTException e) {
                e.printStackTrace();
            }
            KafkaProducer<String, String> producer = new KafkaProducer<String, String>(prop);
            byte[][] imageBytes = screenCapture();
            byte[] flattenedBytes = flatten2DArray(imageBytes);
            String base64EncodedImage = Base64.getEncoder().encodeToString(flattenedBytes);
            String shape=String.format("(%d,%d)",height,width);


            // 创建一个包含 uuid 和 screen 的 jObject
            JSONObject jObject = new JSONObject();
            jObject.put("uuid", uuid);
            jObject.put("shape",shape);
            jObject.put("img_byte", base64EncodedImage);
            // 将 JSONObject 转换为 JSON 字符串
            String jObjectStr = jObject.toJSONString();
            ProducerRecord<String, String> producerRecord1 = new ProducerRecord<>(this.producerTopic[0],"processor_script", jObjectStr);
            producer.send(producerRecord1);
            //ProducerRecord<String, String> producerRecord2 = new ProducerRecord<>(this.producerTopic[1], "processor_script",jObjectStr);
            //producer.send(producerRecord2);
        }
        /*
        else if ("control_action".equals(key)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                JsonNode jsonNode = objectMapper.readTree(value);//其中value是json字符串比如"[{\"key1\":\"value1\"},{\"key2\":\"value2\"},{\"key3\":\"value3\"}]"
                if (jsonNode.isArray()) {
                    for (JsonNode element : jsonNode) {
                        LOG.info(element.toString());
                        actionExec(element.toString());
                        // exception handling needs to be completed
                    }
                }
            } catch (Exception e) {
                // Handle JSON parsing exception
                e.printStackTrace();
            }
            KafkaProducer<String, byte[]> producer = new KafkaProducer<String, byte[]>(prop);
            byte[] s = screenCapture();
            ProducerRecord<String, byte[]> producerRecord1 = new ProducerRecord<>(this.consumer_topic[0], s);
            producer.send(producerRecord1);
            ProducerRecord<String, byte[]> producerRecord2 = new ProducerRecord<>(this.consumer_topic[1], "action exec success!".getBytes());
            producer.send(producerRecord2);
        }

         */

    }
}
